<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Integration of User-Defined Types</title>
<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../index.html" title="Chapter 1. Boost.Convert 2.0">
<link rel="up" href="../index.html" title="Chapter 1. Boost.Convert 2.0">
<link rel="prev" href="converters.html" title="Converters">
<link rel="next" href="algorithms.html" title="Boost.Convert with Standard Algorithms">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
<td align="center"><a href="../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="converters.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="algorithms.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="boost_convert.integration_of_user_types"></a><a class="link" href="integration_of_user_types.html" title="Integration of User-Defined Types">Integration of
    User-Defined Types</a>
</h2></div></div></div>
<p>
      Probably the most obvious way to support a new type is to write a converter
      (potentially by inheriting from an existing converter) that understands the
      type and implements whatever transformation functionality is required. That
      said, conversions to certain types are very common (for example, string/text-related
      conversions) and, consequently, an ability to <span class="emphasis"><em>extend</em></span> support
      of an <span class="emphasis"><em>existing</em></span> converter onto a user-defined type might
      be the preferred option. The obvious example of such design might be the <span class="emphasis"><em><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">iostream</span></code></em></span>
      library and its type-integration mechanism based on
    </p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;,</span> <span class="identifier">Type</span><span class="special">&amp;);</span>       <span class="comment">// For input</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;,</span> <span class="identifier">Type</span> <span class="keyword">const</span><span class="special">&amp;);</span> <span class="comment">// For output</span>
</pre>
<p>
      Within the <span class="emphasis"><em>Boost.Convert</em></span> framework the integration and
      support of user-defined types is every converter's private business. Every
      converter is free to implement its own (or re-use an existing) user-type-integration
      mechanism.
    </p>
<h4>
<a name="boost_convert.integration_of_user_types.h0"></a>
      <span class="phrase"><a name="boost_convert.integration_of_user_types._emphasis_boost__cnv__stream_et_al___emphasis_"></a></span><a class="link" href="integration_of_user_types.html#boost_convert.integration_of_user_types._emphasis_boost__cnv__stream_et_al___emphasis_"><span class="emphasis"><em>boost::cnv::stream
      et al.</em></span></a>
    </h4>
<p>
      Unsurprisingly, the converters based on the <span class="emphasis"><em><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">iostream</span></code></em></span>
      library use the mechanism introduced and supported by that library. That is,
    </p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
          for output <span class="emphasis"><em>Type</em></span> needs to be <span class="emphasis"><em>Output Streamable</em></span>;
        </li>
<li class="listitem">
          for input <span class="emphasis"><em>Type</em></span> needs to be <span class="emphasis"><em>Input Streamable</em></span>.
        </li>
</ul></div>
<p>
      which in practical terms means that the type needs to have the following operators
      defined:
    </p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;,</span> <span class="identifier">Type</span><span class="special">&amp;);</span>       <span class="comment">// For input</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;,</span> <span class="identifier">Type</span> <span class="keyword">const</span><span class="special">&amp;);</span> <span class="comment">// For output</span>
</pre>
<p>
      For example,
    </p>
<p>
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">change</span>
<span class="special">{</span>
    <span class="keyword">enum</span> <span class="identifier">value_type</span> <span class="special">{</span> <span class="identifier">no</span><span class="special">,</span> <span class="identifier">up</span><span class="special">,</span> <span class="identifier">dn</span> <span class="special">};</span>

    <span class="identifier">change</span><span class="special">(</span><span class="identifier">value_type</span> <span class="identifier">v</span> <span class="special">=</span><span class="identifier">no</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">value_</span><span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="special">{}</span>
    <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">==(</span><span class="identifier">change</span> <span class="identifier">v</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">value_</span> <span class="special">==</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">value_</span><span class="special">;</span> <span class="special">}</span>
    <span class="identifier">value_type</span> <span class="identifier">value</span><span class="special">()</span> <span class="keyword">const</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">value_</span><span class="special">;</span> <span class="special">}</span>

    <span class="keyword">private</span><span class="special">:</span> <span class="identifier">value_type</span> <span class="identifier">value_</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
    </p>
<p>
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;</span> <span class="identifier">stream</span><span class="special">,</span> <span class="identifier">change</span><span class="special">&amp;</span> <span class="identifier">chg</span><span class="special">)</span>
<span class="special">{</span>
    <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">str</span><span class="special">;</span> <span class="identifier">stream</span> <span class="special">&gt;&gt;</span> <span class="identifier">str</span><span class="special">;</span>

    <span class="comment">/**/</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">str</span> <span class="special">==</span> <span class="string">"up"</span><span class="special">)</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">;</span>
    <span class="keyword">else</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">str</span> <span class="special">==</span> <span class="string">"dn"</span><span class="special">)</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span><span class="special">;</span>
    <span class="keyword">else</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">str</span> <span class="special">==</span> <span class="string">"no"</span><span class="special">)</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">no</span><span class="special">;</span>
    <span class="keyword">else</span> <span class="identifier">stream</span><span class="special">.</span><span class="identifier">setstate</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">failbit</span><span class="special">);</span>

    <span class="keyword">return</span> <span class="identifier">stream</span><span class="special">;</span>
<span class="special">}</span>

<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;</span> <span class="identifier">stream</span><span class="special">,</span> <span class="identifier">change</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">chg</span><span class="special">)</span>
<span class="special">{</span>
    <span class="keyword">return</span> <span class="identifier">stream</span> <span class="special">&lt;&lt;</span> <span class="special">(</span><span class="identifier">chg</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span> <span class="special">?</span> <span class="string">"up"</span> <span class="special">:</span> <span class="identifier">chg</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span> <span class="special">?</span> <span class="string">"dn"</span> <span class="special">:</span> <span class="string">"no"</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
    </p>
<p>
      That allows handling conversions of user-defined types with <span class="emphasis"><em><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">iostream</span></code></em></span>-based
      converters:
    </p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">cnv</span><span class="special">::</span><span class="identifier">cstream</span>      <span class="identifier">cnv1</span><span class="special">;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">cnv</span><span class="special">::</span><span class="identifier">lexical_cast</span> <span class="identifier">cnv2</span><span class="special">;</span>

<span class="identifier">change</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">;</span>
<span class="identifier">string</span>  <span class="identifier">s1</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">string</span><span class="special">&gt;(</span><span class="identifier">chg</span><span class="special">,</span> <span class="identifier">cnv1</span><span class="special">,</span> <span class="string">"bad"</span><span class="special">);</span>                <span class="comment">// Input type (change) deduced</span>
<span class="identifier">string</span>  <span class="identifier">s2</span> <span class="special">=</span> <span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">string</span><span class="special">,</span> <span class="identifier">change</span><span class="special">&gt;(</span><span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span><span class="special">,</span> <span class="identifier">cnv1</span><span class="special">,</span> <span class="string">"bad"</span><span class="special">);</span> <span class="comment">// Input type (change) enforced</span>

<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">change</span><span class="special">&gt;(</span><span class="string">"up"</span><span class="special">,</span> <span class="identifier">cnv1</span><span class="special">,</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">no</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">change</span><span class="special">&gt;(</span><span class="string">"up"</span><span class="special">,</span> <span class="identifier">cnv2</span><span class="special">,</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">no</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">s1</span> <span class="special">==</span> <span class="string">"up"</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">s2</span> <span class="special">==</span> <span class="string">"dn"</span><span class="special">);</span>
</pre>
<p>
    </p>
<h4>
<a name="boost_convert.integration_of_user_types.h1"></a>
      <span class="phrase"><a name="boost_convert.integration_of_user_types._emphasis_boost__cnv__strtol_et_al___emphasis_"></a></span><a class="link" href="integration_of_user_types.html#boost_convert.integration_of_user_types._emphasis_boost__cnv__strtol_et_al___emphasis_"><span class="emphasis"><em>boost::cnv::strtol
      et al.</em></span></a>
    </h4>
<p>
      Other converters (based on <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">cnv</span><span class="special">::</span><span class="identifier">cnvbase</span></code>) implement support for user types
      similarly but without the <span class="emphasis"><em><code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">iostream</span></code></em></span>-related
      overhead (see <a class="link" href="performance.html#boost_convert.performance.converters_compared" title="Converters Compared">Converters
      Compared</a>). Namely, new types are supported by the converters after the
      following is defined:
    </p>
<pre class="programlisting"><span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">TypeIn</span> <span class="keyword">const</span><span class="special">&amp;,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">TypeOut</span><span class="special">&gt;&amp;);</span>
</pre>
<p>
      For example, the mentioned <span class="emphasis"><em><code class="computeroutput"><span class="identifier">change</span></code></em></span>
      class is deployed with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">cnv</span><span class="special">::</span><span class="identifier">strol</span></code> after the following <span class="emphasis"><em>change-to-string</em></span>
      and <span class="emphasis"><em>string-to-change</em></span> conversions are defined:
    </p>
<p>
</p>
<pre class="programlisting"><span class="keyword">inline</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">change</span> <span class="identifier">chg</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;&amp;</span> <span class="identifier">str</span><span class="special">)</span>
<span class="special">{</span>
    <span class="identifier">str</span> <span class="special">=</span> <span class="identifier">chg</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span> <span class="special">?</span> <span class="string">"up"</span> <span class="special">:</span> <span class="identifier">chg</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span> <span class="special">?</span> <span class="string">"dn"</span> <span class="special">:</span> <span class="string">"no"</span><span class="special">;</span>
<span class="special">}</span>

<span class="keyword">inline</span> <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">str</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">change</span><span class="special">&gt;&amp;</span> <span class="identifier">chg</span><span class="special">)</span>
<span class="special">{</span>
    <span class="comment">/**/</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">str</span> <span class="special">==</span> <span class="string">"up"</span><span class="special">)</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">;</span>
    <span class="keyword">else</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">str</span> <span class="special">==</span> <span class="string">"dn"</span><span class="special">)</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span><span class="special">;</span>
    <span class="keyword">else</span> <span class="keyword">if</span> <span class="special">(</span><span class="identifier">str</span> <span class="special">==</span> <span class="string">"no"</span><span class="special">)</span> <span class="identifier">chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">no</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
    </p>
<p>
      which are not that dissimilar to (but considerably more efficient than) previously
      shown:
    </p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&gt;&gt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&amp;,</span> <span class="identifier">change</span><span class="special">&amp;);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">&lt;&lt;(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">ostream</span><span class="special">&amp;,</span> <span class="identifier">change</span> <span class="keyword">const</span><span class="special">&amp;);</span>
</pre>
<p>
      That allows handling conversions of user-defined types with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">cnv</span><span class="special">::</span><span class="identifier">strtol</span></code>:
    </p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">cnv</span><span class="special">::</span><span class="identifier">strtol</span> <span class="identifier">cnv</span><span class="special">;</span>
<span class="identifier">change</span>          <span class="identifier">up_chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">;</span>
<span class="identifier">change</span>          <span class="identifier">dn_chg</span> <span class="special">=</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span><span class="special">;</span>

<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</span><span class="identifier">up_chg</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="string">"bad"</span><span class="special">)</span> <span class="special">==</span> <span class="string">"up"</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</span><span class="identifier">dn_chg</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="string">"bad"</span><span class="special">)</span> <span class="special">==</span> <span class="string">"dn"</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</span>    <span class="number">12</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="string">"bad"</span><span class="special">)</span> <span class="special">==</span> <span class="string">"12"</span><span class="special">);</span>

<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">change</span><span class="special">&gt;(</span><span class="string">"up"</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">no</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">up</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span><span class="identifier">change</span><span class="special">&gt;(</span><span class="string">"dn"</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">no</span><span class="special">)</span> <span class="special">==</span> <span class="identifier">change</span><span class="special">::</span><span class="identifier">dn</span><span class="special">);</span>
<span class="identifier">BOOST_TEST</span><span class="special">(</span><span class="identifier">convert</span><span class="special">&lt;</span>   <span class="keyword">int</span><span class="special">&gt;(</span><span class="string">"12"</span><span class="special">,</span> <span class="identifier">cnv</span><span class="special">,</span> <span class="special">-</span><span class="number">1</span><span class="special">)</span> <span class="special">==</span> <span class="number">12</span><span class="special">);</span>
</pre>
<p>
    </p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2009-2020 Vladimir Batov<p>
        Distributed under the Boost Software License, Version 1.0. See copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>.
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="converters.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="algorithms.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
